package top.kaoshanji.p2ch16a;

import java.util.ArrayDeque;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 代码清单-p2ch16a-486页a：使用显式锁/条件实现的阻塞队列
 * author kaoshanji
 * ^_^
 * create time 2025/2/26 18:50
 */
public class MyBlockingQueue<E> {

    private Queue<E> queue = null;
    private int limit;

    private Lock lock = new ReentrantLock();

    // 现在有两个条件了...
    private Condition notFull = lock.newCondition(); // 针对添加，不是满的，反过来说，满了就需要等待
    private Condition notEmpty = lock.newCondition(); // 针对获取，不是空的，反过来说，空了就需要等待

    public MyBlockingQueue(int limit) {
        this.limit = limit;
        this.queue = new ArrayDeque<>(limit);
    }


    public void put(E e) throws InterruptedException {
        lock.lockInterruptibly();

        try {
            while (queue.size() == limit) { // 队列已满
                notFull.await();
            }

            queue.add(e);

            notEmpty.signal();
        } finally {
            lock.unlock();
        }
    }

    public E take() throws InterruptedException {
        lock.lockInterruptibly();

        try {
            while (queue.isEmpty()) {
                notEmpty.await();
            }

            E e = queue.poll();

            notFull.signal();

            return e;
        } finally {
            lock.unlock();
        }

    }


}
